import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;

/**
 * The event class is an object representing a specific event on a tour
 * 
 * @author Taylor Becker
 * 
 */
public class Event
{
    // date format
    private static SimpleDateFormat dateFormat;
    static
    {
        // hour: minute AM/PM
        dateFormat = new SimpleDateFormat("h:mm a");
        
        // time zone GMT for simple times since we aren't using date
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    }
    
    private EventType eventType; // type of event this is
    private Time startTime, // scheduled starting time of event
            endTime; // scheduled end time of event
    private List<Provider> providers; // possible providers of the event
    
    /**
     * Initialize event
     * 
     * @param eventType
     *            type of event this is
     * @param startTime
     *            scheduled starting time of event
     * @param endTime
     *            scheduled end time of event
     */
    public Event(EventType eventType, Time startTime, Time endTime)
    {
        setEventType(eventType);
        setStartTime(startTime);
        setEndTime(endTime);
        
        providers = new LinkedList<Provider>();
    }
    
    /**
     * @return type of event this is
     */
    public EventType getEventType()
    {
        return eventType;
    }
    
    /**
     * @return scheduled starting time of event
     */
    public Time getStartTime()
    {
        return startTime;
    }
    
    /**
     * @return scheduled end time of event
     */
    public Time getEndTime()
    {
        return endTime;
    }
    
    /**
     * @return provider for the event
     */
    public Provider getProvider()
    {
        // if we have a provider
        if (!providers.isEmpty())
            return providers.get(0);
        
        return null;
    }
    
    /**
     * @return possible providers for event
     */
    public List<Provider> getProviders()
    {
        return providers;
    }
    
    /**
     * Set type of event
     * 
     * @param type
     *            type of event this is
     */
    private void setEventType(EventType type)
    {
        eventType = type;
    }
    
    /**
     * Set time event starts
     * 
     * @param start
     *            starting time of event
     */
    private void setStartTime(Time start)
    {
        startTime = start;
    }
    
    /**
     * Set time event ends
     * 
     * @param end
     *            ending time of event
     */
    private void setEndTime(Time end)
    {
        endTime = end;
    }
    
    /**
     * Add an event provider to our list of possibles
     * Should this throw an exception if the provider is not open during event time?
     * 
     * @param provider
     *            provider for the event we are adding
     */
    public void addProvider(Provider provider) throws NotOpenException
    {
        if (!(provider.isOpen(getStartTime()) && provider.isOpen(endTime)))
            throw new NotOpenException("Provider is not open during event time!");
        
        providers.add(provider);
    }
    
    /**
     * @return String representation of the event
     */
    public String toString()
    {
        String out = String.format("%-8s\t%s - %s at:\n\n", eventType.toString(), dateFormat.format(startTime), dateFormat.format(endTime));
        
        for (Provider p : providers)
        {
            out += String.format("\t%s\n", p.toString());
        }
        
        return out;
    }
    
    /**
     * Reschedule event to a new time
     * 
     * @param newStart
     *            new time for event to start
     * @param newEnd
     *            new time for event to end
     */
    private void reschedule(Time newStart, Time newEnd)
    {
        setStartTime(newStart);
        setEndTime(newEnd);
    }
    
    /**
     * Test events but making a lot of data and printing(testing toString formatting
     * and other objects contained in an event)
     * and try rescheduling to make sure it is properly updated
     * 
     * @param args
     */
    public static void main(String... args)
    {
        // activity from 1 to 3
        Event e1 = new Event(EventType.ACTIVITY, new Time(60 * 60 * 1000), new Time(60 * 60 * 1000 * 3));
        // provider open from 6am to 6pm, should error since activity is from 1 to 3
        try
        {
            e1.addProvider(new Provider("Park", new Place("NYC Park"), 10, new Time(60 * 60 * 1000 * 6), new Time(60 * 60 * 1000 * 18)));
        }
        catch (NotOpenException noe)
        {
            System.out.println(noe.getMessage());
        }
        System.out.println("e1: " + e1);
        
        // dining event from 3 to 5
        Event e2 = new Event(EventType.DINING, new Time(60 * 60 * 1000 * 3), new Time(60 * 60 * 1000 * 5));
        // provider open 24 hours
        e2.addProvider(new Provider("McDonalds", new Place("Food Court"), 10, new Time(0), new Time(0)));
        e2.addProvider(new Provider("Wendy's", new Place("Food Court"), 10, new Time(0), new Time(0)));
        System.out.println("e2: " + e2);
        
        // lodging event from 10pm to 6am next day
        Event e3 = new Event(EventType.LODGING, new Time(60 * 60 * 1000 * 10), new Time(60 * 60 * 1000 * 30));
        // hotel open 24 hours
        e3.addProvider(new Provider("Marriot", new Place("Marriot"), 10, new Time(0), new Time(0)));
        System.out.println("e3: " + e3);
        
        // reschedule e1 to 9 to 11 because people are sleeping at the time it was scheduled for
        e1.reschedule(new Time(60 * 60 * 1000 * 9), new Time(60 * 60 * 1000 * 11));
        e1.addProvider(new Provider("Park", new Place("NYC Park"), 10, new Time(60 * 60 * 1000 * 6), new Time(60 * 60 * 1000 * 18)));
        System.out.println("e1: " + e1); // did reschedule work?
    }
}
